package server;

import java.util.List;
import java.sql.SQLException;
 
import marauroa.common.crypto.Hash;
import marauroa.common.game.AccountResult;
import marauroa.common.game.CharacterResult;
import marauroa.common.game.IRPZone;
import marauroa.common.game.RPAction;
import marauroa.common.game.RPObject;
import marauroa.common.game.Result;
import marauroa.server.game.db.DAORegister;
import marauroa.server.game.db.AccountDAO;
import marauroa.server.game.db.CharacterDAO;
import marauroa.server.db.TransactionPool;
import marauroa.server.db.DBTransaction;
import marauroa.server.game.rp.IRPRuleProcessor;
import marauroa.server.game.rp.RPServerManager;
 
 
public class Rule implements IRPRuleProcessor {
  private static Rule instance;
 
  private World world = World.get();
 
  private RPServerManager manager;
 
  public static IRPRuleProcessor get() {
    if (instance == null) {
      instance = new Rule();
    }
    return instance;
  }
 
  public void setContext(RPServerManager rpman) {
    manager = rpman;
  }
 
  public boolean checkGameVersion(String game, String version) {
    return game.equals("Chat");
  }
 
  public synchronized void onTimeout(RPObject object) {
    onExit(object);
  }
 
  public synchronized boolean onExit(RPObject object) {
    world.remove(object.getID());
    return true;
  }
 
  public synchronized boolean onInit(RPObject object) {
    IRPZone zone = world.getRPZone(new IRPZone.ID("lobby"));
    zone.add(object);
    return true;
  }
 
  public synchronized void beginTurn() {
  }
 
  public boolean onActionAdd(RPObject caster, RPAction action, List<RPAction> actionList) {
    return true;
  }
 
  public synchronized void endTurn() {
  }
 
  public void execute(RPObject caster, RPAction action) {
    if (action.get("type").equals("chat")) {
      RPObject chat_entry = new RPObject();
      chat_entry.put("text", action.get("text"));
      chat_entry.put("from", caster.get("nick"));
      chat_entry.put("turn", manager.getTurn());
      IRPZone zone = world.getRPZone(new IRPZone.ID(caster.getID().getZoneID()));
      zone.assignRPObjectID(chat_entry);
      zone.add(chat_entry);
    }
  }
 
  public AccountResult createAccount(String username, String password, String email) {
    TransactionPool transactionPool = TransactionPool.get();
    DBTransaction trans = transactionPool.beginWork();
    AccountDAO accountDAO = DAORegister.get().get(AccountDAO.class);
    try {
      if (accountDAO.hasPlayer(trans, username)) {
        return new AccountResult(Result.FAILED_PLAYER_EXISTS, username);
      }
      accountDAO.addPlayer(trans, username, Hash.hash(password), email);
      transactionPool.commit(trans);
      return new AccountResult(Result.OK_CREATED, username);
    } catch (SQLException e1) {
      transactionPool.rollback(trans);
 
      return new AccountResult(Result.FAILED_EXCEPTION, username);
    }
  }
 
  public CharacterResult createCharacter(String username, String character, RPObject template) {
    TransactionPool transactionPool = TransactionPool.get();
    DBTransaction trans = transactionPool.beginWork();
    CharacterDAO characterDAO = DAORegister.get().get(CharacterDAO.class);
    try {
      if (characterDAO.hasCharacter(trans, username, character)) {
        return new CharacterResult(Result.FAILED_PLAYER_EXISTS, character, template);
      }
      IRPZone zone = world.getRPZone(new IRPZone.ID("lobby"));
      RPObject object = new RPObject(template);
      object.put("nick", character);
      zone.assignRPObjectID(object);
      characterDAO.addCharacter(trans, username, character, object);
      transactionPool.commit(trans);
      return new CharacterResult(Result.OK_CREATED, character, object);
    } catch (Exception e1) {
      transactionPool.rollback(trans);
 
      return new CharacterResult(Result.FAILED_EXCEPTION, character, template);
    }
  }
}